using Domain;
using ErrorCode;
using Infrastructure;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using RabbitTraceability.Api.Applications.Command;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace RabbitTraceability.Api.Applications.CommandHandler
{
    /// <summary>
    /// 删除溯源信息的命令处理器
    /// </summary>
    public class DeleteTraceabilityInfoCommandHandler : IRequestHandler<DeleteTraceabilityInfoCommand, bool>
    {
        private readonly IRepository<TraceabilityInfo> _repository;
        private readonly ILogger<DeleteTraceabilityInfoCommandHandler> _logger;
        private readonly DataDbContext _context;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="repository">溯源信息仓储</param>
        /// <param name="logger">日志记录器</param>
        /// <param name="context">数据库上下文</param>
        public DeleteTraceabilityInfoCommandHandler(
            IRepository<TraceabilityInfo> repository,
            ILogger<DeleteTraceabilityInfoCommandHandler> logger,
            DataDbContext context)
        {
            _repository = repository;
            _logger = logger;
            _context = context;
        }

        /// <summary>
        /// 处理删除溯源信息的命令
        /// </summary>
        /// <param name="request">请求命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>是否删除成功</returns>
        public async Task<bool> Handle(DeleteTraceabilityInfoCommand request, CancellationToken cancellationToken)
        {
            _logger.LogInformation("删除溯源信息，溯源编号：{TraceabilityId}", request.TraceabilityId);

            // 参数验证
            if (string.IsNullOrWhiteSpace(request.TraceabilityId))
            {
                _logger.LogWarning("溯源编号不能为空");
                throw new ApiException(ResultCode.参数错误, "溯源编号不能为空");
            }

            // 查询溯源信息
            var traceabilityInfo = await _repository.GetAll()
                .FirstOrDefaultAsync(t => t.TraceabilityId == request.TraceabilityId, cancellationToken);

            if (traceabilityInfo == null)
            {
                _logger.LogWarning("未找到溯源信息，溯源编号：{TraceabilityId}", request.TraceabilityId);
                throw new ApiException(ResultCode.数据不存在, $"未找到溯源编号为 {request.TraceabilityId} 的溯源信息");
            }

            // 获取生产批次，用于删除关联数据
            string productionBatch = traceabilityInfo.ProductionBatch;

            try
            {
                // 使用事务进行删除操作
                using var transaction = await _context.Database.BeginTransactionAsync(cancellationToken);
                try
                {
                    // 1. 删除关联的图片信息
                    var imageInfos = await _context.ImageInfos
                        .Where(i => i.ProductionBatch == productionBatch)
                        .ToListAsync(cancellationToken);
                    if (imageInfos.Any())
                    {
                        _logger.LogInformation("删除关联的图片信息，数量：{Count}", imageInfos.Count);
                        _context.ImageInfos.RemoveRange(imageInfos);
                    }

                    // 2. 删除关联的养殖信息
                    var breedingInfos = await _context.BreedingInfos
                        .Where(b => b.ProductionBatch == productionBatch)
                        .ToListAsync(cancellationToken);
                    if (breedingInfos.Any())
                    {
                        _logger.LogInformation("删除关联的养殖信息，数量：{Count}", breedingInfos.Count);
                        _context.BreedingInfos.RemoveRange(breedingInfos);
                    }

                    // 3. 删除关联的保健信息
                    var healthCareInfos = await _context.HealthCareInfos
                        .Where(h => h.ProductionBatch == productionBatch)
                        .ToListAsync(cancellationToken);
                    if (healthCareInfos.Any())
                    {
                        _logger.LogInformation("删除关联的保健信息，数量：{Count}", healthCareInfos.Count);
                        _context.HealthCareInfos.RemoveRange(healthCareInfos);
                    }

                    // 4. 删除关联的屠宰信息
                    var slaughterInfos = await _context.SlaughterInfos
                        .Where(s => s.ProductionBatch == productionBatch)
                        .ToListAsync(cancellationToken);
                    if (slaughterInfos.Any())
                    {
                        _logger.LogInformation("删除关联的屠宰信息，数量：{Count}", slaughterInfos.Count);
                        _context.SlaughterInfos.RemoveRange(slaughterInfos);
                    }

                    // 5. 删除关联的深加工信息
                    var deepProcessingInfos = await _context.DeepProcessingInfos
                        .Where(d => d.ProductionBatch == productionBatch)
                        .ToListAsync(cancellationToken);
                    if (deepProcessingInfos.Any())
                    {
                        _logger.LogInformation("删除关联的深加工信息，数量：{Count}", deepProcessingInfos.Count);
                        _context.DeepProcessingInfos.RemoveRange(deepProcessingInfos);
                    }

                    // 6. 最后删除溯源信息
                    _context.TraceabilityInfos.Remove(traceabilityInfo);
                    
                    // 保存所有更改
                await _context.SaveChangesAsync(cancellationToken);
                
                    // 提交事务
                    await transaction.CommitAsync(cancellationToken);
                    
                    _logger.LogInformation("删除溯源信息及关联数据成功，溯源编号：{TraceabilityId}", request.TraceabilityId);
                return true;
                }
                catch (Exception ex)
                {
                    // 回滚事务
                    await transaction.RollbackAsync(cancellationToken);
                    _logger.LogError(ex, "删除溯源信息事务执行失败，溯源编号：{TraceabilityId}", request.TraceabilityId);
                    throw new ApiException(ResultCode.服务器错误, "删除溯源信息失败，请稍后再试");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除溯源信息失败，溯源编号：{TraceabilityId}", request.TraceabilityId);
                throw new ApiException(ResultCode.服务器错误, "删除溯源信息失败，请稍后再试");
            }
        }
    }
} 